package com.justenholter.text.effects {
	
	import com.justenholter.text.effects.IEffect;
	
	/**
	 * ...
	 * 
	 * @author justen holter
	 */
	public class Cycle implements IEffect {
		
		private const TAB			:Object = {a:9, b:9};
		private const SPACE			:Object = {a:32, b:32};
		private const MARKS_1		:Object = {a:33, b:47};
		private const NUMBERS		:Object = {a:48, b:57};
		private const MARKS_2		:Object = {a:58, b:64};
		private const UPPER_CASE	:Object = {a:65, b:90};
		private const MARKS_3		:Object = {a:91, b:96};
		private const LOWER_CASE	:Object = {a:97, b:122};
		private const MARKS_4		:Object = {a:123, b:126};
		private const CODES			:Array = new Array(TAB, SPACE, MARKS_1, NUMBERS, MARKS_2, UPPER_CASE, MARKS_3, LOWER_CASE, MARKS_4);
		
		/**
		 * Creates a new instance of Cycle
		 */
		public function Cycle() {
			
		}
		
		/**
		 * loops through CODES and determines what range charCode falls 
		 * within
		 *
		 * @param		code		charCode
		 * @return		object		range of charCodes within the same bracket
		 */
		private function getCodeRange(charCode:Number):* {
			for(var i:Number = 0; i < CODES.length; i++){
				if((charCode >= CODES[i].a) && (charCode <= CODES[i].b)) return CODES[i];
			}
		}
		
		/**
		 * @inheritDoc
		 */
		public function init(curText:String, newText:String):String {
			return next(curText, newText);
		}
		
		/**
		 * @inheritDoc
		 */
		public function next(curText:String, newText:String ):String {
			
			var temp:String = "";
			
			/* move all characters forward one spot in their respective
			 * code ranges */ 
			for(var i:Number = 0; i < Math.min(curText.length + 1, newText.length); i++){
				
				var curChar:Number = curText.charCodeAt(i);
				var newChar:Number = newText.charCodeAt(i);
				
				/* add correct characters to our new string */
				if(curChar == newChar){
					
					temp += newText.charAt(i);
					
				}else{
					
					/* check if the curChar is already within the
					 * newChars codeRange */
					var curBracket:Object = getCodeRange(curChar);
					var newBracket:Object = getCodeRange(newChar);
					
					if(curBracket != newBracket){
						
						//get a random character from the correct bracket
						temp += String.fromCharCode(Math.round(Math.random() * (newBracket.b - newBracket.a + 1)) + newBracket.a);
						
					}else{
						
						//step forward through the bracket
						temp += String.fromCharCode(curChar >= curBracket.b ? curBracket.a : curChar + 1);
					}
				}
			}
			
			return temp;
		}
	}
}